/*
 * Created on Feb 8, 2009
 *
 * TODO
 */
package jacky.lanlan.song.web.filter;

import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * Debug 专用，提供类似 Rails 的请求详细情况日志，这些日志将会被打印到控制台。
 * <p>
 * 配置 showHeaders 初始参数为 true，将打印 HTTP 请求头 <br>
 * 配置 showServletContextParams 初始参数为 true，将打印 context 中的 attribute 键值对 <br>
 * 配置 exclude-url-pattern 初始参数 (正则表达式)，任何匹配该 Pattern 的 URL 请求都将被这个 Filter 忽略而直接发往下一个过滤器。 默认值 <b
 * style="color:red">.+(\.css|\.js|\.png|\.jpg|\.gif)$</b>
 * 
 * <p style="color:red;font-weight:bold"> 建议配置为第一个 Filter 。
 * 
 * @author Jacky.Song
 */
public class DebugFilter implements Filter {

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest http = (HttpServletRequest) request;

		if (excludeURLPattern != null && http.getRequestURL().toString().matches(excludeURLPattern)) {
			chain.doFilter(request, response);
			return;
		}
		
		System.out.println("----------------------------------------------");
		
		System.out.println("Request URL: " + http.getRequestURL());
		System.out.println("QueryString: " + http.getQueryString());
		System.out.println("CharacterEncoding: " + http.getCharacterEncoding());
		System.out.println("HTTP Method: " + http.getMethod());
		
		showParameters(http);

		showRequestAttributes(http);

		showSessionAttribute(http.getSession(false));

		if(showServletContextParams) showContextAttribute();

		if (showHeaders) showHeaders(http);

		showRequestInfo(http);

		System.out.println("----------------------------------------------");

		chain.doFilter(request, response);
	}

	private void showParameters(HttpServletRequest http) {
		System.out.println();
		System.out.println("///////- Parameters -/////// ");
		Map<String, String> params = http.getParameterMap();
		int count = 0;
		for (String name : params.keySet()) {
			count++;
			System.out.printf("(%s: %s)  -  ", name, http.getParameter(name));
			if (count % 5 == 0) System.out.println();
		}
		System.out.println();
	}

	private void showRequestAttributes(HttpServletRequest http) {
		System.out.println();
		System.out.println("///////- Request Attributes -/////// ");
		Enumeration<?> params = http.getAttributeNames();
		int count = 0;
		while (params.hasMoreElements()) {
			count++;
			String name = (String) params.nextElement();
			System.out.printf("(%s: %s)  -  ", name, http.getAttribute(name).toString());
			if (count % 3 == 0) System.out.println();
		}
		System.out.println();
	}

	private void showSessionAttribute(HttpSession session) {
		if (session != null) {
			System.out.println();
			System.out.println("///////- Session Attributes -/////// ");
			Enumeration<?> params = session.getAttributeNames();
			int count = 0;
			while (params.hasMoreElements()) {
				count++;
				String name = (String) params.nextElement();
				System.out.printf("(%s: %s) - ", name, session.getAttribute(name)
						.toString());
				if (count % 3 == 0) System.out.println();
			}
			System.out.println();
		}
	}

	private void showContextAttribute() {
		System.out.println();
		System.out.println("///////- ServletContext Attributes -/////// ");
		Enumeration<?> params = context.getAttributeNames();
		while (params.hasMoreElements()) {
			String name = (String) params.nextElement();
			System.out.printf("%s: %s", name, context.getAttribute(name)
					.toString());
			System.out.println();
			System.out.println();
		}
	}

	private void showHeaders(HttpServletRequest http) {
		System.out.println();
		System.out.println("///////- Headers -/////// ");
		Enumeration<?> headerNames = http.getHeaderNames();
		while (headerNames.hasMoreElements()) {
			String name = (String) headerNames.nextElement();
			System.out.printf("%s: %s", name, http.getHeader(name));
			System.out.println();
			System.out.println();
		}
	}

	private void showRequestInfo(HttpServletRequest http) {
		System.out.println();
		System.out.println("///////- Request Info -/////// ");
		System.out.println("ContentType: " + http.getContentType());
		System.out.println("ContentLength: " + http.getContentLength());
		System.out.println("RequestedSessionId: " + http.getRequestedSessionId());
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		context = filterConfig.getServletContext();
		this.showHeaders = this.parseBooleanParam(filterConfig, "showHeaders");
		this.showServletContextParams = this.parseBooleanParam(filterConfig, "showServletContextParams");
		
		String pattern = filterConfig.getInitParameter("exclude-url-pattern");
		if (pattern!=null) this.excludeURLPattern = pattern;
	}

	private boolean parseBooleanParam(FilterConfig filterConfig,String name) {
		String s = filterConfig.getInitParameter(name);
		return (s!=null && s.equals("true"));
	}
	
	private ServletContext context;

	private boolean showHeaders;
	private boolean showServletContextParams;
	
	private static String excludeURLPattern = ".+(\\.css|\\.js|\\.png|\\.jpg|\\.gif)$"; // 不需要经过这个过滤器的请求URL
																																											// Pattern

}
